#include "../logs/bitlog.h"
#include <vector>
#include <thread>
#include <chrono>
#include <iostream>
#include <string>
#include <memory>

void bench(const std::string& logger_name, size_t thr_count, size_t msg_count, size_t msg_len) {
    // 1.获取日志器
    bitlog::Logger::ptr logger = bitlog::getLogger(logger_name);
    if (logger.get() == nullptr) {
        return;
    }

    std::cout << "测试日志：" << msg_count << "条，总大小" << (msg_count * msg_len) / 1024 << "KB\n";

    // 2.组织指定长度的日志消息
    std::string msg(msg_len - 1, 'A'); // 少一个字节，是为了给末尾到时候添加换行（即给日志消息添加断行）

    // 3. 创建指定数量的线程
    std::vector<std::thread> threads; // 线程数组,用来存储创建的线程
    std::vector<double> cost_arry(thr_count); // 耗时数组，用来存储每个线程的耗时
    size_t msg_per_thr = msg_count / thr_count; // 每个线程要发送的消息数
    for (size_t i = 0; i < thr_count; ++i) {
        threads.emplace_back([&, i]() {
            // 4. 线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now();
            // 5. 循环写入日志
            for (size_t j = 0; j < msg_per_thr; ++j) {
                logger->fatal("%s", msg.c_str());
            }
            // 6. 线程函数内部结束计时
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - start;
            cost_arry[i] = cost.count(); // 线程i的耗时
            std::cout << "线程" << i << ": " << "输出日志数量" << msg_per_thr << ",耗时" << cost.count() << "s" << std::endl;
        });
    }
    for (size_t i = 0; i < thr_count; ++i) {
        threads[i].join();
    }

    // 7. 计算总耗时：在多线程中，每个线程都会耗费时间，但是线程是并发处理的，因此耗时最高的线程时间就是总时间
    double max_cost = cost_arry[0];
    for (size_t i = 1; i < thr_count; ++i) {
        if (cost_arry[i] > max_cost) {
            max_cost = cost_arry[i];
        }
    }
    size_t msg_per_sec = static_cast<size_t>(msg_count / max_cost);
    size_t size_per_sec = static_cast<size_t>((msg_count * msg_len) / max_cost / 1024);
    // 8.进行输出打印
    std::cout << "\t总耗时：" << max_cost << "s\n";
    std::cout << "\t每秒发送日志数量：" << msg_per_sec << "条\n";
    std::cout << "\t每秒发送日志大小：" << size_per_sec << "KB\n";
}

void sync_bench() {
    std::unique_ptr<bitlog::LoggerBuilder> builder(new bitlog::GlobalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(bitlog::LoggerType::LOGGER_SYNC);
    builder->buildSink<bitlog::FileSink>("./logfile/sync.log");
    builder->build();
    bench("sync_logger", 3, 10000000, 100);
}

void async_bench() {
    std::unique_ptr<bitlog::LoggerBuilder> builder(new bitlog::GlobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(bitlog::LoggerType::LOGGER_ASYNC);
    builder->buildEnableUnSafeAsync(); // 启用非安全异步模式---主要是为了将实际落地时间排除在外
    builder->buildSink<bitlog::FileSink>("./logfile/async.log");
    builder->build();
    bench("async_logger", 3, 10000000, 100);
}

int main()
{
    async_bench();
    return 0;
}
